#include "library.h"

#include <QMutexLocker>
#include <numeric>
#include <algorithm>

Library::Library() :
    _books(0),
    _readInterval(100),
    _writeInterval(100),
    _maxBooksCount(0),
    _waitCount(0)
{
    _books.squeeze();
    _books.reserve(_maxBooksCount);
}

size_t Library::getBookCount()
{
    QMutexLocker locker(&_library);

    return _books.size();
}

book_t Library::getBook(size_t index)
{
    _library.lock();
    book_t book = _books[index];
    _library.unlock();

    if (!book->tryLock()) {
        _waitCount++;
        emit waitCountChanged(_waitCount);
        book->lock();
        _waitCount--;
        emit waitCountChanged(_waitCount);
    }

    return book;
}

void Library::returnBook(book_t book)
{
    book->unlock();
}

int Library::addBook()
{
    QMutexLocker locker(&_library);

    if (isFull())
        return -1;

    size_t index = _books.size();
    _books.append(shared_ptr(new QMutex()));

    emit booksCountChanged(_books.size());

    return index;
}

size_t Library::readInterval()
{
    return _readInterval;
}

size_t Library::writeInterval()
{
    return _writeInterval;
}

bool Library::isFull()
{
    return static_cast<size_t>(_books.size()) == _maxBooksCount;
}

void Library::setBooksMaxCount(int maxCount)
{
    QMutexLocker locker(&_library);
    _maxBooksCount = maxCount;
    if (static_cast<size_t>(_books.size()) <= _maxBooksCount)
        _books.reserve(_maxBooksCount);
    else
        _books.resize(_maxBooksCount);

    emit booksCountChanged(_books.size());
}

void Library::setReadInterval(int interval)
{
    _readInterval = interval;
}

void Library::setWriteInterval(int interval)
{
    _writeInterval = interval;
}
